﻿' frmNetworkPlanSample.vb
' compile with: /doc:frmNetworkPlanSample.xml
' <copyright>Copyright (c) Microsoft Corporation. All rights reserved.
' </copyright>
' <summary>This file contains the main form for the Office plan sample.
' </summary>
' 
' <remarks>The Visio Office Plan Sample Application demonstrates the use 
' of the Visio ActiveX Control in an application hosted on a Windows form
' instead of the Microsoft Office Visio drawing environment. A predefined
' set of furniture products is presented to the user as buttons on the form,
' with information on each type and the current quantity shown in a grid.
' The user clicks on the furniture buttons to add furniture shapes to the
' drawing surface, where they can work with the shapes using standard Visio
' operations. A context menu on the shapes includes a command that opens
' a dialog with the details of the furniture item.
' 
' This sample requires that Microsoft Office Visio 2003 is installed with the
' .NET development support option checked.
' 
' Tasks included in this sample include:
' - Create a Visio ActiveX Control as a drawing surface in a form
' - Handle user actions on shapes in the drawing surface
' - Save and reopen the drawing
' - Save and restore application configuration settings
' - Support a context menu on the shapes
' 
' The data is in an XML file and the shapes are in a stencil file. Both
' are included with this sample.
' </remarks>

Imports System
Imports System.Collections.Generic
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Imports Microsoft.Office.Interop.Visio
Imports Microsoft.Office.Interop.VisOcx

' this has to be referenced out of the axVisDrawCtrl project
Imports AxMicrosoft.Office.Interop.VisOcx

Imports System.Windows.Forms

Imports System.Data
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Diagnostics.CodeAnalysis


Imports System.ComponentModel
Imports System.Collections.ObjectModel


Imports axVisDrawCtrl



Partial Public Class frmNetworkPlanSample


#Region " Properties and Definitions "

    ''' <summary>Numeric constants are used to define tolerances and
    ''' shape spacing.</summary>
    Private Const currencyTolerance As Decimal = 0.01D
    Private Const shapeLocationChange As Double = 0.125R

    ''' <summary>The stencil path is the filename of the stencil that
    ''' contains the master shapes used by this sample. It is located in
    ''' the same directory as the application.</summary>
    Private stencilPath As String

    ''' <summary>The application name is displayed in message box captions.
    ''' </summary>
    Private applicationName As String = ""

    ''' <summary>The Visio application.AlertResponse setting is used to
    ''' suppress error and message dialogs.</summary>
    Private alertResponse As Integer

    ''' <summary>The EventSink class handles Visio events.
    ''' </summary>
    Private visioEventSink As EventSink

    ''' <summary>The drawingControlList contains a list of names of
    ''' documents open in the drawing control.</summary>
    Private drawingControlList As New System.Collections.ArrayList()

    ''' <summary>The running totals keep track of the current prices for
    ''' the shapes on the drawing page.</summary>
    Private m_totalRetailPrice As Decimal = 0D
    Private m_totalWholesalePrice As Decimal = 0D

    ''' <summary> The shape that is clicked is needed when processing
    ''' mouse events.</summary>
    Private clickedShape As IVShape

    ''' <summary>The product data is stored in a ProductData object while
    ''' the application is running. Note productData can be null if the
    ''' product database cannot be accessed.</summary>
    Private productData As ProductData

    Private networkDefaults As NetworkShapeDefault()

    ''' <summary>The NetworkShapeDefault structure stores information
    ''' about the products that have both shapes and data. Only products
    ''' with both are supported by the application.</summary>
    Private Structure NetworkShapeDefault
        Public masterName As String
        Public initialLocationX As Double
        Public initialLocationY As Double
    End Structure

    ''' <summary>The TotalRetailPrice property is used to maintain the
    ''' total retail price so that the value can be displayed on the
    ''' form. This property cannot be negative.</summary>
    ''' Suppress this type of warning for all forms. The forms are supposed
    ''' to be localized individually.
    <SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")> _
    Public Property TotalRetailPrice() As Decimal

        Get
            Return m_totalRetailPrice
        End Get

        Set(ByVal value As Decimal)

            ' Make sure that the total price doesn't drop below zero.
            m_totalRetailPrice = Math.Max(0D, value)

            ' Update the label that displays the total retail price.
            ' Floating point math is not precise, so treat any value
            ' less than the currency tolerance as zero.
            If m_totalRetailPrice < currencyTolerance Then
                retailTotal.Text = ""
            Else
                retailTotal.Text = [String].Format(System.Globalization.CultureInfo.CurrentCulture, "{0:c}", m_totalRetailPrice)
            End If
        End Set
    End Property

    ''' <summary>The TotalWholesalePrice property is used to maintain the
    ''' total wholesale price so that the value can be displayed on the
    ''' form. This property cannot be negative.</summary>
    <SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")> _
    Public Property TotalWholesalePrice() As Decimal

        Get
            Return m_totalWholesalePrice
        End Get

        Set(ByVal value As Decimal)

            ' Make sure that the total price doesn't drop below zero.
            m_totalWholesalePrice = Math.Max(0D, value)

            ' Update the label that displays the total wholesale price.
            ' Floating point math is not precise, so treat any value
            ' less than the currency tolerance as zero.
            If m_totalWholesalePrice < currencyTolerance Then
                wholesaleTotal.Text = ""
            Else
                wholesaleTotal.Text = [String].Format(System.Globalization.CultureInfo.CurrentCulture, "{0:c}", m_totalWholesalePrice)
            End If
        End Set
    End Property



    Private _drawingControl As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl
    Public Property drawingControl() As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl
        Get
            Return Me._drawingControl
        End Get
        Set(ByVal value As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl)
            Me._drawingControl = value
        End Set
    End Property

    Private _drawingDocument As Microsoft.Office.Interop.Visio.Document
    Public Property drawingDocument() As Microsoft.Office.Interop.Visio.Document
        Get
            Return Me._drawingDocument
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Document)
            Me._drawingDocument = value
        End Set
    End Property

    Private _drawingApplication As Microsoft.Office.Interop.Visio.Application
    Public Property drawingApplication() As Microsoft.Office.Interop.Visio.Application
        Get
            Return Me._drawingApplication
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Application)
            Me._drawingApplication = value
        End Set
    End Property

    Private _drawingWindow As Microsoft.Office.Interop.Visio.Window
    Public Property drawingWindow() As Microsoft.Office.Interop.Visio.Window
        Get
            Return Me._drawingWindow
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Window)
            Me._drawingWindow = value
        End Set
    End Property

    Private _drawingPage As Microsoft.Office.Interop.Visio.Page
    Public Property drawingPage() As Microsoft.Office.Interop.Visio.Page
        Get
            Return Me._drawingPage
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Page)
            Me._drawingPage = value
        End Set
    End Property


#End Region

#Region " Constructor "

    Dim myData As DataView
    Dim productDataset As System.Data.DataSet = New System.Data.DataSet


    Public Sub New()
        MyBase.New()


        Me.InitializeComponent()

        ' Insert code required on object creation below this point.

        Try



            'get the wrapper for the visio control
            Dim axVisLib As axVisDraw = wfh.Child
            drawingControl = axVisLib.AxDrawingControl


        Catch ex As Exception

            Dim errWin As ErrorWindow = New ErrorWindow("construct", ex)
            errWin.ShowDialog()

        End Try



    End Sub


#End Region



#Region " Form Controls Handlers "



    ''' <summary>The onnetworkButtonClicked method handles the event that
    ''' is raised when one of the furniture buttons is clicked. The
    ''' button text field contains the corresponding name of the master
    ''' shape on the product stencil.</summary>
    ''' <param name="sender">The object that raised the event.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub NetworkButton_Click _
            (ByVal sender As System.Object, _
             ByVal e As System.Windows.RoutedEventArgs)

        Dim networkButton As System.Windows.Controls.Button = DirectCast(sender, System.Windows.Controls.Button)
        Dim masterName As String = networkButton.Name.ToString

        Try

            Dim networkMaster As Master = Nothing
            Dim dropLocationX As Double = 0.0R
            Dim dropLocationY As Double = 0.0R
            Dim shapeNumber As Integer

            ' Get the master shape to drop onto the Visio drawing page.
            networkMaster = Utility.GetMaster(drawingControl, stencilPath, masterName)

            ' The different types of network equipment are dropped on the page at
            ' different initial locations. Check if the master is in
            ' the list of special shapes.
            For shapeNumber = networkDefaults.GetLowerBound(0) To networkDefaults.GetUpperBound(0)

                ' Check for a master name match.
                If masterName = networkDefaults(shapeNumber).masterName Then

                    ' Save the default drop location.
                    dropLocationX = networkDefaults(shapeNumber).initialLocationX
                    dropLocationY = networkDefaults(shapeNumber).initialLocationY

                    Exit For
                End If
            Next

            ' Drop the master at the initial location. The end user
            ' can drag the shape around on the drawing page after it's
            ' dropped.
            Dim targetPage As Microsoft.Office.Interop.Visio.Page
            targetPage = DirectCast(drawingControl.Window.PageAsObj, Microsoft.Office.Interop.Visio.Page)
            targetPage.Drop(networkMaster, dropLocationX, dropLocationY)

            ' Update the initial location for the furniture shape so that
            ' new shapes don't sit directly on top of each other.
            If (shapeNumber >= networkDefaults.GetLowerBound(0)) AndAlso (shapeNumber <= networkDefaults.GetUpperBound(0)) Then

                networkDefaults(shapeNumber).initialLocationX += shapeLocationChange
                networkDefaults(shapeNumber).initialLocationY -= shapeLocationChange

            End If

        Catch [error] As COMException


            ' GetMaster failed to return the master shape so display an
            ' error message and ignore the button click message.
            Dim message As String
            message = Utility.GetResourceString(Strings.MissingMasterError)
            message += Environment.NewLine + masterName
            message += Environment.NewLine + [error].Message

            Utility.RtlAwareMessageBoxShow(Nothing, message, applicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning, alertResponse)
        End Try

    End Sub



    ''' <summary>The onMenuFileNewClicked method handles the event that is
    ''' raised when the user clicks on the File > New command in the
    ''' menu. Since only one document can exist, this operation simply
    ''' clears the current document.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFileNew_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        Const visualFeedbackOn As Integer = 1
        Const visualFeedbackOff As Integer = 0

        Dim result As System.Windows.Forms.DialogResult
        Dim visioApplication As Microsoft.Office.Interop.Visio.Application

        ' Only one document can be open.
        ' Prompt user to save changes before closing the current document.
        result = Utility.SaveDrawing(drawingControl, True)

        If System.Windows.Forms.DialogResult.Cancel <> result Then

            visioApplication = DirectCast(drawingControl.Window.Application, Microsoft.Office.Interop.Visio.Application)

            drawingControl.Src = ""

            ' Get the current state of the visual feedback. If visual
            ' feedback is on the end user will see changes in the drawing
            ' window as the code operates on the shapes.
            Dim visualFeedbackStatus As Integer = visioApplication.ScreenUpdating

            ' Don't let the user see the visual feedback while the shapes
            ' are deleted.
            If visualFeedbackStatus = visualFeedbackOn Then
                visioApplication.ScreenUpdating = visualFeedbackOff
            End If

            ' Delete all of the shapes from the Visio window.
            ' Note: when invoking Selection.Delete(), the EventSink class will raise
            ' an event and call onRemoveProductInformation for each shape deleted
            ' from the page. That will update the product data and grid control.
            Dim targetWindow As Microsoft.Office.Interop.Visio.Window
            targetWindow = DirectCast(drawingControl.Window, Microsoft.Office.Interop.Visio.Window)
            If targetWindow.PageAsObj.Shapes.Count > 0 Then
                targetWindow.SelectAll()
                targetWindow.Selection.Delete()
            End If

            ' Set the document saved flag since the drawing control is now
            ' displaying a blank document.
            drawingControl.Document.Saved = True

            ' Restore the screen updating status.
            If visualFeedbackStatus = visualFeedbackOn Then
                visioApplication.ScreenUpdating = visualFeedbackOn
            End If
        End If

    End Sub



    ''' <summary>The onMenuFileOpenClicked method handles the event that is
    ''' raised when the user clicks on the File > Open command in the
    ''' menu. Either a document or stencil can be opened.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFileOpen_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        Dim openFileDialog As OpenFileDialog = Nothing
        Dim targetDocuments As Documents
        Dim fileName As String
        Dim fileNameForCompare As String
        Dim shapeNumber As Integer

        Try
            ' Set up the open file dialog and let the user select the
            ' file to open.
            openFileDialog = New OpenFileDialog()
            openFileDialog.Title = Utility.GetResourceString(Strings.OpenDialogTitle)
            openFileDialog.Filter = Utility.GetResourceString(Strings.OpenDialogFilter)
            openFileDialog.FilterIndex = 1
            openFileDialog.InitialDirectory = System.Windows.Forms.Application.StartupPath

            If openFileDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then

                ' The user selected a valid file name and hit OK. Get the
                ' file name from the dialog and open the file.
                fileName = openFileDialog.FileName
                fileNameForCompare = fileName.ToUpper(System.Globalization.CultureInfo.CurrentCulture)
                If (fileNameForCompare.IndexOf(Strings.VssSuffix, StringComparison.OrdinalIgnoreCase) > 0) OrElse (fileNameForCompare.IndexOf(Strings.VsxSuffix, StringComparison.OrdinalIgnoreCase) > 0) Then

                    targetDocuments = DirectCast(drawingControl.Window.Application.Documents, Documents)

                    ' Open the stencil read-only.
                    targetDocuments.OpenEx(fileName, CShort(VisOpenSaveArgs.visOpenRO) + CShort(VisOpenSaveArgs.visOpenDocked))

                ElseIf (fileNameForCompare.IndexOf(Strings.VsdSuffix, StringComparison.OrdinalIgnoreCase) > 0) OrElse (fileNameForCompare.IndexOf(Strings.VdxSuffix, StringComparison.OrdinalIgnoreCase) > 0) Then

                    Dim result As DialogResult

                    ' Only one document can be open.
                    ' Prompt user to save changes before closing the current
                    ' document.
                    result = Utility.SaveDrawing(drawingControl, True)

                    If System.Windows.Forms.DialogResult.Cancel <> result Then

                        drawingControl.Src = ""
                        removeAllProducts()

                        ' Open the new document.
                        drawingControl.Src = fileName
                        drawingControl.Document.Saved = True

                        ' Setup the drawing, open the product stencil, and
                        ' start the event sink.
                        ' Note that opening a different drawing will close
                        ' the previous drawing and end the previous event sink.
                        setUpVisioDrawing()

                        ' Read the shapes in the document and update the
                        ' information in the data grid and totals.
                        Dim eventArgs As New EventArgs()

                        Dim targetPage As Microsoft.Office.Interop.Visio.Page
                        targetPage = drawingControl.Window.PageAsObj

                        For shapeNumber = 1 To targetPage.Shapes.Count

                            onAddProductInformation(targetPage.Shapes(shapeNumber), eventArgs)
                        Next
                    End If
                End If
            End If
        Finally


            ' Make sure the dialog is cleaned up.
            If openFileDialog IsNot Nothing Then
                openFileDialog.Dispose()
            End If
        End Try

    End Sub


    ''' <summary>The onMenuFileCloseClicked method handles the event that is
    ''' raised when the user clicks on the File > Close command in the
    ''' menu. Since only one document can exist, this operation is
    ''' identical to the Menu > New command.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFileClose_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        menuFileNew_Click(sender, e)
    End Sub

    ''' <summary>The onMenuFileSaveClicked method handles the event that is
    ''' raised when the end user clicks on the File > Save command in the
    ''' menu.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFileSave_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        ' Prompt user to save changes.
        Utility.SaveDrawing(drawingControl, False)

    End Sub



    ''' <summary>The onMenuFilePrintPreviewClicked method handles the event
    ''' that is raised when the user clicks on the Print Preview
    ''' command in the menu. The System.Drawing.Printing objects are used
    ''' to provide print preview to the user.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFilePrintPreview_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        Try

            Dim printDocument As System.Drawing.Printing.PrintDocument = Nothing
            Dim printPreviewDialog As PrintPreviewDialog = Nothing

            ' Create a print document to handle the print preview
            ' functionality. This assumes the default settings.
            printDocument = New System.Drawing.Printing.PrintDocument()

            ' Add the local print page handler to print document. This
            ' allows the page image to be used as the printed graphics.
            AddHandler printDocument.PrintPage, AddressOf Me.onPrintDocumentPrintPage

            ' Create a print preview dialog and show it to the user. The
            ' handler will process the actual print.
            printPreviewDialog = New PrintPreviewDialog()
            printPreviewDialog.Document = printDocument
            printPreviewDialog.ShowDialog()

        Catch [error] As System.Drawing.Printing.InvalidPrinterException
            ' Utility.RtlAwareMessageBoxShow(Me, [error].Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, alertResponse)
        End Try
    End Sub


    ''' <summary>The onMenuFileExitClicked method handles the event that is
    ''' raised when the end user clicks on the File > Exit command in the
    ''' menu.</summary>
    ''' <param name="sender">The object that raised the event. This is
    ''' ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub menuFileExit_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)

        Me.Close()

    End Sub



    ''' <summary>The onMenuProductInformationClicked method handles the
    ''' event that is raised when the display product information item on
    ''' a network shape's right mouse menu is selected.</summary>
    ''' <param name="sender">The object that raised the event. This is
    ''' ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub DisplayProductInfo_Click _
                (ByVal sender As System.Object, _
                 ByVal e As System.Windows.RoutedEventArgs)
        Try
            If productData Is Nothing Then
                Dim message As String

                message = Utility.GetResourceString(Strings.ProductDataNotAvailableErrorMessage)
                Throw New ArgumentException(message)
            End If

            Dim masterName As String

            Select Case sender.name.ToString

                Case "cmmiServer"
                    masterName = "Server"
                Case "cmmiPC"
                    masterName = "PC"
                Case "cmmiRouter"
                    masterName = "Router"
                Case Else
                    Exit Sub
            End Select

            Dim networkMaster As Master = Nothing
            Dim dropLocationX As Double = 0.0R
            Dim dropLocationY As Double = 0.0R


            ' Get the master shape to drop onto the Visio drawing page.
            networkMaster = Utility.GetMaster(drawingControl, stencilPath, masterName)

            Dim targetShape As Microsoft.Office.Interop.Visio.Shape = networkMaster.Shapes(1)

            Dim productDetailDialog As frmNetworkProductDetail = Nothing

            ' Create the product details dialog for the clicked shape from
            ' the product data and the metafile.
            productDetailDialog = New frmNetworkProductDetail _
                    (productData, _
                     Utility.ProductId(targetShape))

            Dim selShape As Microsoft.Office.Interop.Visio.Selection
            selShape = productDetailDialog.shapeWindow.Selection

            ' Drop the master at the initial location. The end user
            ' can drag the shape around on the drawing page after it's
            ' dropped.
            Dim targetPage As Microsoft.Office.Interop.Visio.Page
            targetPage = DirectCast(productDetailDialog.shapeControl.Window.PageAsObj, Microsoft.Office.Interop.Visio.Page)
            Dim pageSheet As Microsoft.Office.Interop.Visio.Shape = targetPage.PageSheet


            If pageSheet.CellExists("pagewidth", False) = True Then
                dropLocationX = pageSheet.Cells("pagewidth").ResultIU / 2
            End If

            If pageSheet.CellExists("pageheight", False) = True Then
                dropLocationY = pageSheet.Cells("pageheight").ResultIU / 2
            End If

            targetPage.Drop(networkMaster, dropLocationX, dropLocationY)

            selShape = productDetailDialog.shapeWindow.Selection
            ' clear the selection so that we don't loop back again
            productDetailDialog.shapeWindow.CenterViewOnShape(selShape(1), VisCenterViewFlags.visCenterViewDefault)
            productDetailDialog.shapeWindow.DeselectAll()

            productDetailDialog.ShowDialog()


            productDetailDialog = Nothing



        Catch [error] As ArgumentException


            ' Display the error.
            Utility.DisplayException(Strings.ApplicationErrorMessage, [error], alertResponse)
        Catch ex As Exception

            Dim errWin As ErrorWindow = New ErrorWindow("productinfo context", ex)
            errWin.ShowDialog()
        End Try
    End Sub

#End Region

#Region " Visio Handlers "


    ''' <summary>The onShapeDoubleClick method handles the
    ''' marker event that is raised when the user double-clicks on
    ''' a shape from the sample office furniture stencil.</summary>
    ''' <param name="sender">The Visio shape double-clicked by the user.
    ''' </param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub onShapeDoubleClick _
                (ByVal sender As Object, ByVal e As System.EventArgs)

        Dim productDetailDialog As frmNetworkProductDetail = Nothing

        Try


            Dim targetShape As IVShape

            targetShape = DirectCast(sender, IVShape)

            ' Create the product details dialog for the clicked shape from
            ' the product data and the metafile.
            productDetailDialog = New frmNetworkProductDetail _
                    (productData, _
                     Utility.ProductId(targetShape))

            Dim intCt As Integer = drawingWindow.Selection.Count
            If intCt < 1 Then Exit Sub

            Dim pastePage As Microsoft.Office.Interop.Visio.Page = productDetailDialog.shapePage
            Dim selShape As Microsoft.Office.Interop.Visio.Selection
            Dim pasteWindow As Microsoft.Office.Interop.Visio.Window = productDetailDialog.shapeWindow
            selShape = drawingWindow.Selection

            CopyAndPasteSelection( _
                    selShape, _
                    Microsoft.Office.Interop.Visio. _
                        VisCutCopyPasteCodes.visCopyPasteNoTranslate, _
                    pastePage)


            selShape = pasteWindow.Selection
            ' clear the selection so that we don't loop back again
            pasteWindow.CenterViewOnShape(selShape(1), VisCenterViewFlags.visCenterViewDefault)
            pasteWindow.DeselectAll()
            drawingWindow.DeselectAll()

            productDetailDialog.ShowDialog()

            productDetailDialog = Nothing

        Catch [error] As ApplicationException
            ' Display the error.
            Utility.DisplayException(Strings.ApplicationErrorMessage, [error], alertResponse)

        Catch ex As Exception

            Dim errWin As ErrorWindow = New ErrorWindow("shapedblclick", ex)
            errWin.ShowDialog()

        End Try

        If productDetailDialog IsNot Nothing Then
            productDetailDialog = Nothing
        End If

    End Sub


    Private Function CopyAndPasteSelection( _
            ByVal selectionToCopy As Microsoft.Office.Interop.Visio.Selection, _
            ByVal flags As Object, _
            ByVal pastePage As Microsoft.Office.Interop.Visio.Page) _
            As Boolean

        Dim methodSucceeded As Boolean = False

        Try

            ' Copy the selection with the flags specified.
            selectionToCopy.Copy(flags)

            ' Paste the selection onto the destination page.
            pastePage.Paste(flags)

            methodSucceeded = True

        Catch err As System.Runtime.InteropServices.COMException
            System.Diagnostics.Debug.WriteLine(err.Message)
        Catch ex As Exception
            Dim errWin As ErrorWindow = New ErrorWindow("copypasteselection", ex)
            errWin.ShowDialog()
        End Try

        Return methodSucceeded

    End Function




    ''' <summary>The onPrintDocumentPrintPage method handles the event that
    ''' is raised when the end user hits Print in the print dialog.
    ''' </summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event.</param>
    Private Sub onPrintDocumentPrintPage _
            (ByVal sender As Object, _
             ByVal e As System.Drawing.Printing.PrintPageEventArgs)

        Const metafileOriginX As Integer = 0
        Const metafileOriginY As Integer = 0
        Dim pageWidth As Double = 0
        Dim pageHeight As Double = 0
        Dim temporaryShape As Microsoft.Office.Interop.Visio.Shape
        Dim targetPage As Microsoft.Office.Interop.Visio.Page

        targetPage = DirectCast(drawingControl.Window.PageAsObj, Microsoft.Office.Interop.Visio.Page)

        ' draw a frame around the page so the bounding box of the
        ' picture is the size of the page.
        pageWidth = targetPage.PageSheet.CellsSRC(CShort(Microsoft.Office.Interop.Visio.VisSectionIndices.visSectionObject), CShort(Microsoft.Office.Interop.Visio.VisRowIndices.visRowPage), CShort(Microsoft.Office.Interop.Visio.VisCellIndices.visPageWidth)).ResultIU

        pageHeight = targetPage.PageSheet.CellsSRC(CShort(Microsoft.Office.Interop.Visio.VisSectionIndices.visSectionObject), CShort(Microsoft.Office.Interop.Visio.VisRowIndices.visRowPage), CShort(Microsoft.Office.Interop.Visio.VisCellIndices.visPageHeight)).ResultIU

        temporaryShape = targetPage.DrawRectangle(0, 0, pageWidth, pageHeight)

        temporaryShape.CellsSRC(CShort(Microsoft.Office.Interop.Visio.VisSectionIndices.visSectionObject), CShort(Microsoft.Office.Interop.Visio.VisRowIndices.visRowFill), CShort(Microsoft.Office.Interop.Visio.VisCellIndices.visFillPattern)).ResultIU = 0

        ' Make the line white so it's not visible on the page.
        temporaryShape.CellsSRC(CShort(Microsoft.Office.Interop.Visio.VisSectionIndices.visSectionObject), CShort(Microsoft.Office.Interop.Visio.VisRowIndices.visRowLine), CShort(Microsoft.Office.Interop.Visio.VisCellIndices.visLineColor)).ResultIU = 1

        ' Create a metafile with the image of the page.
        'Dim printMetafile As New System.Drawing.Imaging.Metafile(DirectCast(targetPage.Picture.Handle, IntPtr), False)

        Dim ptrMetafile As IntPtr = CType(targetPage.Picture.Handle, IntPtr)
        Dim printMetafile = New System.Drawing.Imaging.Metafile(ptrMetafile, False)

        temporaryShape.Delete()

        ' Put the image into the graphics of the print document. This
        ' causes the page image to be printed.
        e.Graphics.DrawImage(printMetafile, metafileOriginX, metafileOriginY)


    End Sub

    ''' <summary>The setUpVisioDrawing method initializes the Visio drawing
    ''' that is displayed in the drawing control.</summary>
    ''' <remarks>This method throws a COMException on error.</remarks>
    Private Sub setUpVisioDrawing()

        Dim pageLeft As Double
        Dim pageTop As Double
        Dim pageWidth As Double
        Dim pageHeight As Double
        Dim distanceBetweenShapes As Double
        Dim nextShapeXLocation As Double
        Dim networkShapeNumber As Integer

        Try

            ' Cache the application name for use in message box captions.
            applicationName = drawingControl.Window.Application.Name

            ' Cache the AlertResponse setting in a member variable.
            alertResponse = drawingControl.Window.Application.AlertResponse

            ' Hide all built-in docked windows (shape search, 
            ' custom properties, etc.).
            For i As Integer = drawingControl.Window.Windows.Count To 1 Step -1
                Dim visWindow As Microsoft.Office.Interop.Visio.Window
                Dim windowType As Integer

                visWindow = drawingControl.Window.Windows.ItemEx(i)
                windowType = visWindow.Type

                If windowType = CInt(VisWinTypes.visAnchorBarBuiltIn) Then

                    Select Case visWindow.ID
                        Case CInt(VisWinTypes.visWinIDCustProp), CInt(VisWinTypes.visWinIDDrawingExplorer), CInt(VisWinTypes.visWinIDMasterExplorer), CInt(VisWinTypes.visWinIDPanZoom), CInt(VisWinTypes.visWinIDShapeSearch), CInt(VisWinTypes.visWinIDSizePos), _
                        CInt(VisWinTypes.visWinIDStencilExplorer)

                            visWindow.Visible = False
                            Exit Select
                        Case Else

                            Exit Select
                    End Select
                End If
            Next

            ' Use the Visio window to set the visible user
            ' interface parts of the window.
            Dim targetWindow As Microsoft.Office.Interop.Visio.Window
            targetWindow = DirectCast(drawingControl.Window, Microsoft.Office.Interop.Visio.Window)

            Dim targetApplication As Microsoft.Office.Interop.Visio.Application
            targetApplication = DirectCast(targetWindow.Application, Microsoft.Office.Interop.Visio.Application)

            targetApplication.Settings.EnableAutoConnect = False

            targetWindow.ShowRulers = 0
            targetWindow.ShowPageTabs = False
            targetWindow.ShowScrollBars = 0
            targetWindow.ShowGrid = 0
            targetWindow.Zoom = 1.0R

            ' Position the furniture shapes relative to the page.
            targetWindow.GetViewRect(pageLeft, pageTop, pageWidth, pageHeight)

            'initialize pretty much everything
            drawingApplication = targetWindow.Application
            drawingWindow = drawingApplication.ActiveWindow
            drawingDocument = drawingApplication.ActiveDocument
            drawingPage = drawingApplication.ActivePage

            Dim intNetwork As Integer = networkDefaults.GetLength(0)
            If intNetwork < 1 Then
                Dim msgWin As ErrorWindow = New ErrorWindow("FurnitureArray < 1")
                msgWin.ShowDialog()
                Exit Sub
            End If

            ' Space the shapes evenly across the center of the page.
            distanceBetweenShapes = pageWidth / (networkDefaults.GetLength(0) + 1)
            nextShapeXLocation = pageLeft + distanceBetweenShapes

            For networkShapeNumber = networkDefaults.GetLowerBound(0) To networkDefaults.GetUpperBound(0)
                ' The X location is set, then stepped forward for the next shape.
                networkDefaults(networkShapeNumber).initialLocationX = nextShapeXLocation
                nextShapeXLocation += distanceBetweenShapes

                ' The Y location is always in the center.
                networkDefaults(networkShapeNumber).initialLocationY = pageTop - (pageHeight / 2.0R)
            Next

            ' Start the event sink.
            initializeEventSink()

            ' Open the stencil with the product shapes.
            openNetworkStencil()


            ' The drawing control is displaying a newly opened document.
            ' Set the saved flag to true.
            drawingControl.Document.Saved = True
            drawingControl.PageSizingBehavior = VisPageSizingBehaviors.visNeverResizePages



        Catch [error] As COMException

            ' Display the error.
            Utility.DisplayException(Strings.ComErrorMessage, [error], alertResponse)
            Throw
        End Try

        Exit Sub
    End Sub

    ''' <summary>The initializeEventSink method initializes the event sink
    ''' on the document.</summary>
    Private Sub initializeEventSink()

        Dim targetDocument As Document
        Dim targetApplication As Microsoft.Office.Interop.Visio.Application

        Try

            ' Release the previous event sink.
            visioEventSink = Nothing

            ' Create an event sink to hook up events to the Visio
            ' application and document.
            visioEventSink = New EventSink()
            targetApplication = DirectCast(drawingControl.Window.Application, Microsoft.Office.Interop.Visio.Application)
            targetDocument = DirectCast(drawingControl.Document, Document)

            visioEventSink.AddAdvise(targetApplication, targetDocument)

            ' Listen to shape add events from the Visio event sink.
            ' OnAddProductInformation will be called when a shape is added.
            AddHandler visioEventSink.OnShapeAdd, AddressOf onAddProductInformation

            ' Listen to shape delete events from the Visio event sink.
            ' OnRemoveProductInformation will be called when a shape is deleted.
            AddHandler visioEventSink.OnShapeDelete, AddressOf onRemoveProductInformation

            ' Listen to marker events raised when the user double-clicks a shape.
            ' OnShapeDoubleClick will be called when the user double-clicks
            ' a shape whose double-click event runs the QueueMarkerEvent addon.
            AddHandler visioEventSink.OnShapeDoubleClick, AddressOf onShapeDoubleClick

        Catch [error] As COMException
            ' Display the error.
            Utility.DisplayException(Strings.ComErrorMessage, [error], alertResponse)
            Throw
        End Try
    End Sub

    ''' <summary>The openProductStencil method opens the stencil that
    ''' contains the product master shapes.</summary>
    Private Sub openProductStencil()

        Try

            stencilPath = (System.Windows.Forms.Application.StartupPath & "\") + Utility.GetResourceString(Strings.ProductStencilFilename)

            ' Open the stencil that contains the master shapes.
            Utility.OpenStencil(drawingControl, stencilPath)

        Catch [error] As COMException


            ' OpenStencil failed to open the requested stencil so display an
            ' error message and continue to run.

            Dim message As String
            message = Utility.GetResourceString(Strings.MissingStencilError)
            message += Environment.NewLine + stencilPath
            message += Environment.NewLine + [error].Message

            Utility.RtlAwareMessageBoxShow(Me, message, applicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning, alertResponse)
        End Try
    End Sub

    ''' <summary>The openNetworkStencil method opens the stencil that
    ''' contains the product master shapes.</summary>
    Private Sub openNetworkStencil()

        Try

            stencilPath = (System.Windows.Forms.Application.StartupPath & "\") + Utility.GetResourceString(Strings.NetworkStencilFilename)

            ' Open the stencil that contains the master shapes.
            Utility.OpenStencil(drawingControl, stencilPath)

        Catch [error] As COMException


            ' OpenStencil failed to open the requested stencil so display an
            ' error message and continue to run.

            Dim message As String
            message = Utility.GetResourceString(Strings.MissingStencilError)
            message += Environment.NewLine + stencilPath
            message += Environment.NewLine + [error].Message

            Utility.RtlAwareMessageBoxShow(Me, message, applicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning, alertResponse)
        End Try
    End Sub


    ''' <summary>The onDrawingControlVisibleChanged method handles the
    ''' event that is raised when the Visio ActiveX control has been fully
    ''' initialized. This handler is an alternative to the form-load
    ''' event for initializing the ActiveX control.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    Private Sub onDrawingControlVisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs)

        ' If the drawing control is not on the list of initialized
        ' drawing controls, the control needs to be initialized.
        If (drawingControl.Visible) AndAlso (Not drawingControlList.Contains(drawingControl.Name)) Then

            ' Setup the drawing, open the product stencil and start the
            ' event sink.
            setUpVisioDrawing()

            ' Since all of the initialization tasks succeeded, save
            ' the drawing control in the list of initialized controls.
            drawingControlList.Add(drawingControl.Name)
        End If
    End Sub



    ''' <summary>The onRemoveProductInformation method handles the shape delete
    ''' event that is raised by the EventSink class.
    ''' It removes the information on the form that is from the specified shape.
    ''' </summary>
    ''' <param name="sender">ID of the product to remove.</param>
    ''' <param name="e">The arguments associated with the event
    ''' This is ignored for this case.</param>
    Private Sub onRemoveProductInformation(ByVal sender As Object, ByVal e As EventArgs)

        Try
            If productData Is Nothing Then
                Dim message As String

                message = Utility.GetResourceString(Strings.ProductDataNotAvailableErrorMessage)
                Throw New ArgumentException(message)
            End If

            Dim productId As Integer = CInt(sender)

            ' Only process a valid product ID.
            If productId <> productData.InvalidProductId Then

                ' Update the total prices and the data grid to
                ' remove the information from the deleted shape.
                TotalRetailPrice -= productData.GetRetailPrice(productId)
                TotalWholesalePrice -= productData.GetWholesalePrice(productId)
                productData.RemoveProduct(productId)
            End If

            Me.productsDataGrid.ItemsSource = productData.ProductDataTable.DefaultView

        Catch [error] As ArgumentException


            ' Display the error.
            Utility.DisplayException(Strings.ApplicationErrorMessage, [error], alertResponse)
        End Try
    End Sub

    ''' <summary>The onAddProductInformation method handles the shape added
    ''' event that is raised by the EventSink class.
    ''' It adds the information associated with the new shape to the
    ''' information on the form.</summary>
    ''' <remarks>The new shape can be a group shape that contains multiple
    ''' products. This method recurses into the added shape and adds product
    ''' information for all product sub shapes to the form.</remarks>
    ''' <param name="sender">The Visio shape that was added to the drawing.
    ''' </param>
    ''' <param name="e">The arguments associated with the event.
    ''' This is ignored for this case.</param>
    Private Sub onAddProductInformation(ByVal sender As Object, ByVal e As EventArgs)
        Try
            If productData Is Nothing Then
                Dim message As String

                message = Utility.GetResourceString(Strings.ProductDataNotAvailableErrorMessage)
                Throw New ArgumentException(message)
            End If

            Dim addedShape As IVShape = DirectCast(sender, IVShape)

            ' Get the product ID from the shape.
            Dim productId As Integer = Utility.ProductId(addedShape)

            ' Only process a valid product ID.
            If productId <> productData.InvalidProductId Then

                ' Update the total prices and the data grid to
                ' add the information from the new shape.
                TotalRetailPrice += productData.GetRetailPrice(productId)
                TotalWholesalePrice += productData.GetWholesalePrice(productId)
                productData.AddProduct(productId)
            Else

                ' Recurse into sub shapes to get all product information
                ' that may be contained by this shape.
                For index As Integer = 1 To addedShape.Shapes.Count
                    onAddProductInformation(addedShape.Shapes(index), e)
                Next
            End If

            Me.productsDataGrid.ItemsSource = productData.ProductDataTable.DefaultView


        Catch [error] As ArgumentException


            ' Display a dialog box and consume the exception.
            Utility.DisplayException(Strings.ApplicationErrorMessage, [error], alertResponse)
        End Try
    End Sub

#End Region

#Region " Methods "

    ''' <summary>The onOfficePlanSampleFormLoad method handles the event
    ''' that is raised when the Office Plan Sample form is loaded. Initial
    ''' setup is done in this method.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>
    ''' 

    Private Sub onNetworkPlanSampleFormLoaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Try

            ' Disable the command buttons while the form is being set up.
            ' They will be re-enabled when the form set up is complete.
            router.IsEnabled = False
            pc.IsEnabled = False
            server.IsEnabled = False

            ' The networkDefaults array contains the product information
            ' for the products that have corresponding shapes in the Visio
            ' stencil and buttons on the form. These are the only
            ' furniture types that are supported by this application.
            networkDefaults = New NetworkShapeDefault(2) {}

            ' The following assumes the button text is the master name.
            networkDefaults(0).masterName = server.Name.ToString
            networkDefaults(1).masterName = router.Name.ToString
            networkDefaults(2).masterName = pc.Name.ToString

            ' The product data is set up by reading the data from the
            ' product information file and saving it to a data set. The
            ' data grid on the form is also set up.
            setupProductData()

            ' Re-enable the buttons now that the setup is done.
            router.IsEnabled = True
            pc.IsEnabled = True
            server.IsEnabled = True

            ' Setup the drawing, open the product stencil and start the
            ' event sink.
            setUpVisioDrawing()

            ' Since all of the initialization tasks succeeded, save
            ' the drawing control in the list of initialized controls.
            drawingControlList.Add(drawingControl.Name)


        Catch ex As Exception

            Dim errWin As ErrorWindow = New ErrorWindow("FormLoadedEvent ", ex)
            errWin.ShowDialog()

        End Try




    End Sub





    ''' <summary>The removeAllProducts removes all rows from the
    ''' product data table and resets the running totals.</summary>
    Private Sub removeAllProducts()

        ' Reset product data.
        If productData IsNot Nothing Then
            productData.Clear()
        End If

        ' Reset the totals.
        TotalRetailPrice = 0D
        TotalWholesalePrice = 0D

    End Sub

    ''' <summary>The setUpProductData method reads the product data from
    ''' the product information file into a data set that will be used
    ''' while the application is running. After the data set is
    ''' populated, the data grid on the form is set up and populated.
    ''' </summary>
    ''' <remarks>Throws an exception on error.</remarks>
    Private Sub setupProductData()

        Try



            ' Create and initialize the product data storage. This
            ' contains the product data while the application is running.
            productData = New ProductData()

            productData.SetupProductData()

            'productDataSet.Locale = System.Globalization.CultureInfo.CurrentCulture
            'productDataset.ReadXml((System.Windows.Forms.Application.StartupPath & "\") + Utility.GetResourceString(Strings.ProductDataFilename), System.Data.XmlReadMode.ReadSchema)
            Dim productDatatable As System.Data.DataTable
            productDatatable = productData.ProductDataTable.Copy

            productsDataGrid.ItemsSource = productDatatable.DefaultView


        Catch [error] As System.Security.SecurityException

            Utility.DisplayException(Strings.SecurityErrorMessage, [error], alertResponse)
        Catch [error] As System.IO.FileNotFoundException
            Utility.DisplayException(Strings.FileNotFoundErrorMessage, [error], alertResponse)
        Catch [error] As COMException
            Utility.DisplayException(Strings.ComErrorMessage, [error], alertResponse)
        End Try

        Exit Sub
    End Sub



#End Region


    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub




    ''' <summary>The onNetworkPlanSampleFormClosing method handles the
    ''' event that is raised when the application form is closed.</summary>
    ''' <param name="sender">The object that raised the event. This
    ''' is ignored for this case.</param>
    ''' <param name="e">The arguments associated with the
    ''' event. This is ignored for this case.</param>

    Private Sub Screen_1_Unloaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
        Dim result As DialogResult

        ' Prompt user to save changes before closing the current document.
        result = Utility.SaveDrawing(drawingControl, True)

    

    End Sub


    Private Sub menuHelpAbout_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

        Dim dlgAbout As System.Windows.Window = New About
        dlgAbout.ShowDialog()

    End Sub


End Class

